home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fscache / fscacheReadAhead.c < prev    next >
C/C++ Source or Header  |  1990-12-11  |  9KB  |  357 lines

  1. /* 
  2.  * fsReadAhead.c 
  3.  *
  4.  *    Routines to implement read ahead.  Read ahead is synchronized
  5.  *    with regular writes to a file to avoid inconsistencies.
  6.  *
  7.  * Copyright 1986 Regents of the University of California.
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /sprite/src/kernel/fscache/RCS/fscacheReadAhead.c,v 9.5 90/12/11 00:17:03 mgbaker Exp $ SPRITE (Berkeley)";
  13. #endif not lint
  14.  
  15. #include <sprite.h>
  16. #include <fs.h>
  17. #include <fsutil.h>
  18. #include <fsio.h>
  19. #include <fsStat.h>
  20. #include <fscache.h>
  21. #include <fsNameOps.h>
  22. #include <fsdm.h>
  23. #include <fsrmt.h>
  24. #include <fscacheBlocks.h>
  25.  
  26. /* 
  27.  * Number of blocks to read ahead.  Zero turns off read ahead.
  28.  */
  29. Boolean    fscache_NumReadAheadBlocks = 0;
  30. Boolean    fscache_RATracing = TRUE;
  31.  
  32.  
  33. #define    LOCKPTR    (&readAheadPtr->lock)
  34. typedef struct {
  35.     Fscache_FileInfo    *cacheInfoPtr;
  36.     Fscache_ReadAheadInfo    *readAheadPtr;
  37.     Fscache_Block    *blockPtr;
  38.     int            blockNum;
  39. } ReadAheadCallBackData;
  40.  
  41. static void DoReadAhead _ARGS_((ClientData data, Proc_CallInfo *callInfoPtr));
  42. static void IncReadAheadCount _ARGS_((Fscache_ReadAheadInfo *readAheadPtr));
  43. static void DecReadAheadCount _ARGS_((Fscache_ReadAheadInfo *readAheadPtr));
  44.  
  45.  
  46. /*
  47.  *----------------------------------------------------------------------
  48.  *
  49.  * Fscache_ReadAheadInit --
  50.  *
  51.  *    Read ahead the next block in the cache
  52.  *
  53.  * Results:
  54.  *    None.
  55.  *
  56.  * Side effects:
  57.  *    Read ahead process may be started.
  58.  *
  59.  *----------------------------------------------------------------------
  60.  */
  61. void
  62. Fscache_ReadAheadInit(readAheadPtr)
  63.     register    Fscache_ReadAheadInfo *readAheadPtr;
  64. {
  65.     bzero((Address) readAheadPtr, sizeof(Fscache_ReadAheadInfo));
  66.     Sync_LockInitDynamic(&readAheadPtr->lock, "Fs:readAheadLock");
  67. }
  68.  
  69. /*
  70.  *----------------------------------------------------------------------
  71.  *
  72.  * Fscache_ReadAheadSyncLockCleanup --
  73.  *
  74.  *    Clean up the Sync_Lock tracing info for the read ahead lock.
  75.  *
  76.  * Results:
  77.  *    None.
  78.  *
  79.  * Side effects:
  80.  *    As above.
  81.  *
  82.  *----------------------------------------------------------------------
  83.  */
  84. /*ARGSUSED*/
  85. void
  86. Fscache_ReadAheadSyncLockCleanup(readAheadPtr)
  87.     Fscache_ReadAheadInfo *readAheadPtr;
  88. {
  89.     Sync_LockClear(&readAheadPtr->lock);
  90. }
  91.  
  92. /*
  93.  *----------------------------------------------------------------------
  94.  *
  95.  * FscacheReadAhead --
  96.  *
  97.  *    Read ahead the next block in the cache
  98.  *
  99.  * Results:
  100.  *    None.
  101.  *
  102.  * Side effects:
  103.  *    Read ahead process may be started.
  104.  *
  105.  *----------------------------------------------------------------------
  106.  */
  107. void
  108. FscacheReadAhead(cacheInfoPtr, blockNum)
  109.     register    Fscache_FileInfo *cacheInfoPtr;
  110.     int                blockNum;
  111. {
  112.     int                i;
  113.     ReadAheadCallBackData    *callBackData;
  114.     Fscache_ReadAheadInfo        *readAheadPtr;
  115.     Boolean            openForWriting;
  116.     Fscache_Block        *blockPtr;
  117.     Boolean            found;
  118. #ifdef SOSP91
  119.     Boolean        isForeign = FALSE;    /* Due to migration? */
  120. #endif SOSP91
  121.  
  122. #ifdef SOSP91
  123.     if (proc_RunningProcesses[0] != (Proc_ControlBlock *) NIL) {
  124.     if ((proc_RunningProcesses[0]->state == PROC_MIGRATED) ||
  125.         (proc_RunningProcesses[0]->genFlags &
  126.         (PROC_FOREIGN | PROC_MIGRATING))) {
  127.         isForeign = TRUE;
  128.     }
  129.     }
  130. #endif SOSP91
  131.     switch (cacheInfoPtr->hdrPtr->fileID.type) {
  132.     case FSIO_LCL_FILE_STREAM: {
  133.         register Fsio_FileIOHandle *handlePtr =
  134.             (Fsio_FileIOHandle *)cacheInfoPtr->hdrPtr;
  135.         openForWriting = (handlePtr->use.write > 0);
  136.         readAheadPtr = &handlePtr->readAhead;
  137.         break;
  138.     }
  139.     case FSIO_RMT_FILE_STREAM: {
  140.         register Fsrmt_FileIOHandle *rmtHandlePtr =
  141.             (Fsrmt_FileIOHandle *)cacheInfoPtr->hdrPtr;
  142.         openForWriting = (rmtHandlePtr->rmt.recovery.use.write > 0);
  143.         readAheadPtr = &rmtHandlePtr->readAhead;
  144.         break;
  145.     }
  146.     default:
  147.         panic("FscacheReadAhead, bad stream type <%d>\n",
  148.         cacheInfoPtr->hdrPtr->fileID.type);
  149.         return;
  150.     }
  151.  
  152.     if (fscache_NumReadAheadBlocks == 0 || openForWriting > 0 ||
  153.         FscacheAllBlocksInCache(cacheInfoPtr)) {
  154.     /*
  155.      * Don't do read ahead if there is no read ahead, the file is
  156.      * open for writing, or all the blocks are already in the cache.
  157.      * Read ahead is disallowed if the file is open for writing because
  158.      * read ahead is done without the handle locked and it is unsafe to
  159.      * be reading and writing a file at the same time.
  160.      */
  161.     return;
  162.     }
  163.     for (i = blockNum; i < blockNum + fscache_NumReadAheadBlocks; i++) {
  164.     if (i * FS_BLOCK_SIZE > cacheInfoPtr->attr.lastByte) {
  165.         return;
  166.     }
  167.     Fscache_FetchBlock(cacheInfoPtr, i,
  168.           FSCACHE_DATA_BLOCK | FSCACHE_DONT_BLOCK | FSCACHE_READ_AHEAD_BLOCK,
  169.           &blockPtr, &found);
  170.     if (found) {
  171.         if (blockPtr != (Fscache_Block *) NIL) {
  172.         Fscache_UnlockBlock(blockPtr, 0, -1, 0, 0);
  173.         }
  174.         continue;
  175.     }
  176.  
  177.     fs_Stats.blockCache.readAheads++;
  178. #ifdef SOSP91
  179.     if (isForeign) {
  180.         fs_SospMigStats.blockCache.readAheads++;
  181.     }
  182. #endif SOSP91
  183.     IncReadAheadCount(readAheadPtr);
  184.     callBackData = mnew(ReadAheadCallBackData);
  185.     callBackData->cacheInfoPtr = cacheInfoPtr;
  186.     callBackData->readAheadPtr = readAheadPtr;
  187.     callBackData->blockNum = i;
  188.     callBackData->blockPtr = blockPtr;
  189.     Proc_CallFunc(DoReadAhead, (ClientData) callBackData, 0);
  190.     }
  191. }
  192.  
  193. /*
  194.  *----------------------------------------------------------------------
  195.  *
  196.  * DoReadAhead --
  197.  *
  198.  *    Actually read ahead the given block.
  199.  *
  200.  * Results:
  201.  *    None.
  202.  *
  203.  * Side effects:
  204.  *    The given block is read in.
  205.  *
  206.  *----------------------------------------------------------------------
  207.  */
  208. static void
  209. DoReadAhead(data, callInfoPtr)
  210.     ClientData        data;
  211.     Proc_CallInfo    *callInfoPtr;
  212. {
  213.     register    Fscache_FileInfo *cacheInfoPtr;
  214.     register    ReadAheadCallBackData *callBackData;
  215.     register    Fscache_Block    *blockPtr;
  216.     ReturnStatus        status;
  217.  
  218.     callBackData = (ReadAheadCallBackData *) data;
  219.  
  220.     cacheInfoPtr = callBackData->cacheInfoPtr;
  221.     blockPtr = callBackData->blockPtr;
  222.  
  223.     status = (cacheInfoPtr->backendPtr->ioProcs.blockRead)
  224.         (cacheInfoPtr->hdrPtr, blockPtr, (Sync_RemoteWaiter *)NIL);
  225.     if (status != SUCCESS) {
  226.     fs_Stats.blockCache.domainReadFails++;
  227.     Fscache_UnlockBlock(blockPtr, 0, -1, 0, FSCACHE_DELETE_BLOCK);
  228.     } else {
  229.     Fscache_UnlockBlock(blockPtr, 0, -1, 0, 0);
  230.     }
  231.     DecReadAheadCount(callBackData->readAheadPtr);
  232.     free((Address) callBackData);
  233.     callInfoPtr->interval = 0;    /* don't call us again */
  234. }
  235.  
  236. /*
  237.  *----------------------------------------------------------------------------
  238.  *
  239.  * Fscache_WaitForReadAhead --
  240.  *
  241.  *    Block the caller until the read ahead count on this handle goes to
  242.  *    zero.  Called before a write.
  243.  *
  244.  * Results:
  245.  *    None.
  246.  *
  247.  * Side effects:
  248.  *    Blocks read-ahead until FscacheAllowReadAhead is called.
  249.  *
  250.  *----------------------------------------------------------------------------
  251.  *
  252.  */
  253. ENTRY void
  254. Fscache_WaitForReadAhead(readAheadPtr)
  255.     Fscache_ReadAheadInfo *readAheadPtr;
  256. {
  257.     LOCK_MONITOR;
  258.  
  259.     while (readAheadPtr->count > 0) {
  260.     (void) Sync_Wait(&readAheadPtr->done, FALSE);
  261.     }
  262.     readAheadPtr->blocked = TRUE;
  263.  
  264.     UNLOCK_MONITOR;
  265. }
  266.  
  267. /*
  268.  *----------------------------------------------------------------------------
  269.  *
  270.  * Fscache_AllowReadAhead --
  271.  *
  272.  *    Indicate that it is ok to initiate read ahead.  Called when a
  273.  *    write completes.
  274.  *
  275.  * Results:
  276.  *    None.
  277.  *
  278.  * Side effects:
  279.  *    Notifies the okToRead condition.
  280.  *
  281.  *----------------------------------------------------------------------------
  282.  *
  283.  */
  284. ENTRY void
  285. Fscache_AllowReadAhead(readAheadPtr)
  286.     Fscache_ReadAheadInfo *readAheadPtr;
  287. {
  288.     LOCK_MONITOR;
  289.  
  290.     readAheadPtr->blocked = FALSE;
  291.     Sync_Broadcast(&readAheadPtr->okToRead);
  292.  
  293.     UNLOCK_MONITOR;
  294. }
  295.  
  296. /*
  297.  *----------------------------------------------------------------------------
  298.  *
  299.  * IncReadAheadCount --
  300.  *
  301.  *    Increment the number of read aheads on this file.  This will block
  302.  *    if read aheads are blocked because of a write.
  303.  *
  304.  * Results:
  305.  *    None.
  306.  *
  307.  * Side effects:
  308.  *    Increment the number of read aheads on the file.
  309.  *
  310.  *----------------------------------------------------------------------------
  311.  *
  312.  */
  313. static void
  314. IncReadAheadCount(readAheadPtr)
  315.     Fscache_ReadAheadInfo *readAheadPtr;
  316. {
  317.     LOCK_MONITOR;
  318.  
  319.     while (readAheadPtr->blocked) {
  320.     (void) Sync_Wait(&readAheadPtr->okToRead, FALSE);
  321.     }
  322.     readAheadPtr->count++;
  323.  
  324.     UNLOCK_MONITOR;
  325. }
  326.  
  327. /*
  328.  *----------------------------------------------------------------------------
  329.  *
  330.  * DecReadAheadCount --
  331.  *
  332.  *    Decrement the number of read aheads on this file.
  333.  *
  334.  * Results:
  335.  *    None.
  336.  *
  337.  * Side effects:
  338.  *    Read ahead count is decremented and if it goes to zero a broadcast 
  339.  *    is done on the handles condition.
  340.  *
  341.  *----------------------------------------------------------------------------
  342.  *
  343.  */
  344. static void
  345. DecReadAheadCount(readAheadPtr)
  346.     Fscache_ReadAheadInfo *readAheadPtr;
  347. {
  348.     LOCK_MONITOR;
  349.  
  350.     readAheadPtr->count--;
  351.     if (readAheadPtr->count == 0) {
  352.     Sync_Broadcast(&readAheadPtr->done);
  353.     }
  354.  
  355.     UNLOCK_MONITOR;
  356. }
  357.